home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 7 / Gekikoh Dennoh Club Vol. 7 (Japan).7z / Gekikoh Dennoh Club Vol. 7 (Japan) (Track 01).bin / games / otoko / source.lzh / FuncEnemy / lboss04.c < prev    next >
C/C++ Source or Header  |  1999-06-14  |  19KB  |  736 lines

  1. /* 4面ボス */
  2. #include <xsp2lib.h>
  3.  
  4. #include "../otoko.h"
  5. #include "../player.h"
  6. #include "../enemy.h"
  7. #include "../eshot.h"
  8. #include "../effect.h"
  9. #include "../priority.h"
  10. #include "../entry.h"
  11. #include "../sound.h"
  12. #include "../psearch.h"
  13.  
  14. #ifdef DEBUG
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include "../txfont.h"
  18. #endif
  19.  
  20. #define HP_0    6000        /* 耐久力 */
  21. #define HP_1    4000        /* 耐久力がこれ以下になったらカバー破棄 */
  22. #define HP_2    1500        /* 耐久力がこれ以下になったら最終攻撃 */
  23. #define HP_3    300        /* 耐久力がこれ以下になったら味方機のレーザー登場 */
  24.  
  25. #define TIMER_0    19000        /* これ以上時間が経過したらカバー破棄 */
  26. #define TIMER_1    24000        /*      〃      最終形態に */
  27. #define TIMER_2    28000        /*      〃      自爆 */
  28.  
  29.  
  30.  
  31. #define SPEED_1        3    /* 登場時の加速度 */
  32. #define SPEED_1N    25    /* 加速度を足す回数 */
  33.  
  34. #define SPEED_2        6    /* 下に降りてくる時の加速度 */
  35. #define SPEED_2N    35    /* 加速度を足す回数 */
  36.  
  37. #define SPEED_3        20    /* 耳が生えている時の加速度 */
  38. #define SPEED_3N    10    /* 加速度を足す回数 */
  39.  
  40. #define SEQ_DAMAGE    5    /* p->seq がこれ以降だとダメージを受ける */
  41. #define SEQ_DEATH    6
  42.  
  43.  
  44.  
  45. enum {
  46.     MOVETO_INIT = 0,    /* 初期状態 */
  47.     MOVETO_C2L,        /* 中央から左に移動 */
  48.     MOVETO_L2C,
  49.     MOVETO_C2R,
  50.     MOVETO_R2C,
  51.     MOVETO_DOWN,
  52.     MOVETO_DOWN2LEFT,
  53.     MOVETO_UP
  54. };
  55.  
  56. static short EnemyMoveLBoss04 (ENEMY *);
  57. static void EnemyTiniLBoss04 (ENEMY *);
  58.  
  59.  
  60. void EnemyInitLBoss04 (ENEMY * p)
  61. {
  62.     p->vx = 0;
  63.     p->vy = -4 * 65536;
  64.  
  65.     /* 出現時の当たり判定(画面下から出てくるので判定なし) */
  66.     p->hit_px = p->hit_py = p->hit_sx = p->hit_sy = p->hit_cx = 0;
  67.     p->timer = 0;
  68.     p->damage = 0;
  69.     p->flash = 0;
  70.     p->hp = HP_0;
  71.     p->pt = obj_lboss04 + 10;
  72.     p->core_pt = obj_lboss04 + 9;
  73.     p->core_info = 0;
  74.     p->seq = 0;
  75.     p->m_work = 0;
  76.     p->func_enemy_move = EnemyMoveLBoss04;
  77.     p->func_enemy_tini = EnemyTiniLBoss04;
  78.  
  79.     p->parts1 = p->parts2 = 0;
  80.  
  81.     entry_counter_stop = !0;/* エントリーカウンター停止 */
  82. }
  83.  
  84.  
  85.  
  86. static short EnemyMoveLBoss04 (ENEMY * p)
  87. {
  88.     /* 速度を足して上位ワード(固定整数部)だけ取り出す */
  89.     p->x = (p->lx += p->vx) >> 16;
  90.     p->y = (p->ly += p->vy) >> 16;
  91.     p->timer++;
  92.  
  93. #ifdef DEBUG
  94.     {
  95.         char temp_str[64];
  96.         sprintf (temp_str, "TIMER %05hd", p->timer);
  97.         TxfontCursor (20, 3);
  98.         TxfontPuts (temp_str);
  99.         sprintf (temp_str, "   HP %05hd", p->hp);
  100.         TxfontCursor (20, 4);
  101.         TxfontPuts (temp_str);
  102.     }
  103. #endif
  104.  
  105.     switch (p->seq) {
  106.     case 0:
  107.         if (SHORT_LY < 222) {
  108.             p->seq++;
  109.         }
  110.         break;
  111.  
  112.         /* 減速 */
  113.     case 1:
  114.         p->vy += 4096;
  115.         if (p->vy > 16384) {
  116.             p->seq++;
  117.         }
  118.         break;
  119.  
  120.         /* 翼を広げる */
  121.     case 2:
  122.         p->pt++;
  123.         if (p->pt == obj_lboss04 + 30)
  124.             SoundSetSE (SE_LOCK_L);    /* 「がちゃん」という効果音を鳴らす */
  125.         if (p->pt == obj_lboss04 + 55)
  126.             SoundSetSE (SE_LOCK_M);    /* 「がちゃん」という効果音を鳴らす */
  127.         if (p->pt >= obj_lboss04 + 60) {
  128.             p->vy -= 2048;
  129.             if (p->vy < 0)
  130.                 p->vy = 0;
  131.         }
  132.         if (p->pt >= obj_lboss04 + 73) {
  133.             p->seq++;
  134.             /* 第1形態の当り判定 */
  135.             p->hit_px = 24;
  136.             p->hit_py = 8;
  137.             p->hit_sx = 24;
  138.             p->hit_sy = 8;
  139.             p->hit_cx = 24;
  140.             p->m_work = MOVETO_INIT;    /* 移動方向 */
  141.             p->m_work3 = 0;    /* 肩or翼を破壊したか */
  142.             p->s_work = 0;
  143.             p->s_work3 = 0;    /* 直線弾用 */
  144.             p->pt = obj_lboss04;
  145.             p->parts1 = EnemyInit (ENEMY_LBOSS04S, -32, 0, 0, p);    /* 左肩 */
  146.             p->parts2 = EnemyInit (ENEMY_LBOSS04S, 32, 0, 0, p);    /* 右肩 */
  147.         }
  148.         break;
  149.  
  150.         /* 第1形態 */
  151.     case 3:        /* 左右に移動 */
  152.         /* まず移動処理 */
  153.         if (p->m_work == MOVETO_INIT) {
  154.             /* 初期状態なら */
  155.             if (p->x > player->x)
  156.                 p->m_work = 3;    /* 移動方向 */
  157.             else
  158.                 p->m_work = 1;    /* 移動方向 */
  159.             p->m_work2 = 0;
  160.         }
  161.         if (p->m_work2 == 0) {
  162.             /* 初回なら */
  163.             signed short dx, dy;
  164.             signed short dx_table[5] =
  165.             {0, 96 + 16, 128 + 16, 256 - 96 + 16, 128 + 16};
  166.             short m_work_list[15] =
  167.             {MOVETO_L2C, MOVETO_C2R, MOVETO_R2C, MOVETO_C2L,
  168.              MOVETO_L2C, MOVETO_C2R, MOVETO_R2C, MOVETO_C2L,
  169.              MOVETO_L2C, MOVETO_C2R, MOVETO_R2C,
  170.              MOVETO_DOWN, MOVETO_DOWN2LEFT, MOVETO_UP, MOVETO_C2L,};
  171.             unsigned char speed;
  172.             signed short count;
  173.  
  174.             p->m_work2 = !0;
  175.             /* 順に左→中央→右→中央→左へ移動 */
  176.             switch (p->m_work) {
  177.             case 11:    /* 下に降りてくる */
  178.                 p->work = p->x;
  179.                 p->work2 = p->y;
  180.                 speed = SPEED_2;
  181.                 count = SPEED_2N;
  182.                 dx = 144;
  183.                 dy = 256 + 16;
  184.                 p->m_work++;
  185.                 break;
  186.             case 12:    /* 左に避ける */
  187.                 speed = SPEED_1;
  188.                 count = SPEED_1N;
  189.                 dx = 64;
  190.                 dy = p->y - 32;
  191.                 p->m_work++;
  192.                 break;
  193.             case 13:    /* 上に上がる */
  194.                 speed = SPEED_2;
  195.                 count = SPEED_2N;
  196.                 dx = p->work;
  197.                 dy = p->work2;
  198.                 if ((p->parts1) && (p->parts1->parts1)) {
  199.                     p->parts1->parts1->s_work++;
  200.                     p->parts1->parts1->s_work2 = 0;
  201.                     p->parts1->parts1->s_work3 = 0;
  202.                 }
  203.                 if ((p->parts2) && (p->parts2->parts1)) {
  204.                     p->parts2->parts1->s_work++;
  205.                     p->parts2->parts1->s_work2 = 0;
  206.                     p->parts2->parts1->s_work3 = 0;
  207.                 }
  208.                 p->m_work++;
  209.                 break;
  210.             case 10:
  211.                 if (p->m_work3)    /* 肩がなければもう下に降りない */
  212.                     p->m_work = 14;
  213.                 /* ここに break がない事に注意 */
  214.             default:
  215.                 speed = SPEED_1;
  216.                 count = SPEED_1N;
  217.                 dx = dx_table[m_work_list[p->m_work]];
  218.                 /* player->x は乱数の種として使用しています */
  219.                 if (SHORT_LY < 80)
  220.                     dy = (((unsigned short) rndtable[(player->x) & 0xff]) / 4 + 32 + 16);
  221.                 else
  222.                     dy = 64;
  223.                 if (p->m_work < 14)
  224.                     p->m_work++;
  225.                 else
  226.                     p->m_work = 0;
  227.                 break;
  228.             }
  229.  
  230.             /* 移動方向を設定 */
  231.             SubEnemyMoveToInit (p, dx, dy, speed, count);
  232.         } else {
  233.             /* 設定値に従って移動 */
  234.             if (SubEnemyMoveTo (p) < 0)
  235.                 p->m_work2 = 0;    /* 移動方向再設定 */
  236.         }
  237.  
  238.         /* 肩パーツが消えたか? */
  239.         if ((p->parts1) && (p->parts1->child_death))
  240.             p->parts1 = 0;    /* これ以降参照しない */
  241.         if ((p->parts2) && (p->parts2->child_death))
  242.             p->parts2 = 0;    /* これ以降参照しない */
  243.  
  244.         if (((p->parts1 == 0)    /* 左肩がない */
  245.              ||((p->parts1) && (p->parts1->parts1 == 0)))    /* または左翼がない */
  246.             &&        /* なおかつ */
  247.             ((p->parts2 == 0)    /* 右肩がない */
  248.              ||((p->parts2) && (p->parts2->parts1 == 0)))) {    /* または右翼がない */
  249.             p->m_work3 = !0;
  250.         }
  251.         /* 両肩がない場合 */
  252.         if ((p->parts1 == 0) && (p->parts2 == 0)) {
  253.             p->seq++;
  254.             p->m_work = 0;
  255.             SubEnemyMoveToAbort (p);
  256.         }
  257.         break;
  258.  
  259.     case 4:
  260.         /* 設定値に従って移動 */
  261.         if (SubEnemyMoveTo (p) < 0) {
  262.             if (p->m_work == 0) {
  263.                 /* 移動方向を設定 */
  264.                 SubEnemyMoveToInit (p, 144, 96, SPEED_1, SPEED_1N);
  265.                 p->m_work++;
  266.             } else {
  267.                 p->seq++;
  268.                 p->m_work = MOVETO_INIT;    /* 移動方向 */
  269.                 p->s_work = p->s_work2 = 0;
  270.                 p->parts1_work = 30;    /* 左耳復活までの時間( =0 で復活) */
  271.                 p->parts1_work2 = 12;    /* 復活可能回数 */
  272.                 p->parts2_work = 60;    /* 右耳復活までの時間( =0 で復活) */
  273.                 p->parts2_work2 = 12;    /* 復活可能回数 */
  274.                 //p->parts1_work2 = 1;    /* 復活可能回数 */
  275.                 //p->parts2_work2 = 1;    /* 復活可能回数 */
  276.             }
  277.         }
  278.         break;
  279.  
  280.  
  281.         /* 第2形態 */
  282.     case 5:        /* 復活する耳が生える */
  283.         /* まず移動処理 */
  284.         if (p->m_work == MOVETO_INIT) {
  285.             /* 初期状態なら */
  286.             if (p->x > player->x)
  287.                 p->m_work = MOVETO_C2L;    /* 移動方向 */
  288.             else
  289.                 p->m_work = MOVETO_C2R;    /* 移動方向 */
  290.             p->m_work2 = 0;
  291.         }
  292.         if (p->m_work2 == 0) {
  293.             /* 初回なら */
  294.             signed short dx, dy;
  295.             signed short dx_table[5] =
  296.             {0, 72 + 16, 128 + 16, 256 - 72 + 16, 128 + 16};
  297.             short m_work_table[5] =
  298.             {MOVETO_INIT, MOVETO_L2C, MOVETO_C2R, MOVETO_R2C, MOVETO_C2L};
  299.  
  300.             p->m_work2 = !0;
  301.             /* 順に左→中央→右→中央→左へ移動 */
  302.             dx = dx_table[p->m_work];
  303.             p->m_work = m_work_table[p->m_work];
  304.  
  305.             /* player->x は乱数の種として使用しています */
  306.             if (SHORT_LY < 80)
  307.                 dy = (((unsigned short) rndtable[(player->x) & 0xff]) / 4 + 32 + 16);
  308.             else
  309.                 dy = 64;
  310.             /* 移動方向を設定 */
  311.             SubEnemyMoveToInit (p, dx, dy, SPEED_3, SPEED_3N);
  312.         } else {
  313.             /* 設定値に従って移動 */
  314.             if (SubEnemyMoveTo (p) < 0)
  315.                 p->m_work2 = 0;    /* 移動方向再設定 */
  316.         }
  317.  
  318.         /* 耳が消えたら復活までの時間を設定 */
  319.         if ((p->parts1) && (p->parts1->child_death)) {
  320.             p->parts1 = 0;    /* これ以降参照しない */
  321.             p->parts1_work = 110;
  322.         }
  323.         if ((p->parts2) && (p->parts2->child_death)) {
  324.             p->parts2 = 0;    /* これ以降参照しない */
  325.             p->parts2_work = 80;    /* 実は右耳の方が復活が早い */
  326.         }
  327.         /* 耳発生・復活処理 */
  328.         if ((p->parts1_work) && (p->parts1_work2)) {
  329.             p->parts1_work--;
  330.             if (p->parts1_work == 0)
  331.                 p->parts1 = EnemyInit (ENEMY_LBOSS04E, -16, 0, p->parts1_work2--, p);    /* 左翼 */
  332.         }
  333.         if ((p->parts2_work) && (p->parts2_work2)) {
  334.             p->parts2_work--;
  335.             if (p->parts2_work == 0)
  336.                 p->parts2 = EnemyInit (ENEMY_LBOSS04E, 16, 0, p->parts2_work2--, p);    /* 右翼 */
  337.         }
  338.         /* 次に攻撃処理 */
  339.         switch (p->s_work) {
  340. #define S_WORK_LAST    6
  341.         case 0:
  342.             if ((p->hp < HP_1) || (p->timer > TIMER_0)
  343.                 || (((p->parts1_work2 == 0) && (p->parts1 == 0))
  344.                 && ((p->parts2_work2 == 0) && (p->parts2 == 0)))) {
  345.                 p->s_work++;
  346.                 p->s_work2 = 0;
  347.             }
  348.             break;
  349.  
  350.             /* しばらく待つ */
  351.         case 1:
  352.             p->s_work2++;
  353.             if (p->s_work2 >= 55) {
  354.                 p->s_work++;
  355.                 /* 破壊した時のみ得点あり */
  356.                 if (p->hp < HP_1)
  357.                     p->parts3 = EnemyInit (ENEMY_LBOSS04V, p->x, p->y, 0, p);    /* カバーを分離 */
  358.                 else
  359.                     p->parts3 = EnemyInit (ENEMY_LBOSS04V, p->x, p->y, 1, p);    /* カバーを分離 */
  360.                 p->hp = HP_1;    /* ここで強制的に耐久力を HP_1 に */
  361.                 EffectInit (EFFECT_EXPL, 0, p->x, p->y);
  362.                 SoundSetSE (SE_EXPL_M);    /* 中ボス爆発音 */
  363.                 if (!eshot_erase)
  364.                     eshot_erase = ESHOT_ERASE;    /* 弾消し */
  365.                 p->pt = obj_lboss04 + 7;
  366.                 if (standard_play)    /* 標準設定か? */
  367.                     p->core_info = PALET_CORE_RED | PRIORITY_BOSS_CORE;
  368.                 else
  369.                     p->core_info = PALET_CORE_BLUE | PRIORITY_BOSS_CORE;
  370.             }
  371.             break;
  372.  
  373.             /* カバーが消えるまで待つ */
  374.         case 2:
  375.             if ((p->parts3) && (p->parts3->child_death)) {
  376.                 p->parts3 = 0;    /* これ以降参照しない */
  377.                 p->s_work++;
  378.                 p->s_work2 = p->s_work3 = p->s_work4 = 0;
  379.                 /* 当り判定 */
  380.                 p->hit_px = 40;
  381.                 p->hit_py = 16;
  382.                 p->hit_sx = 40;
  383.                 p->hit_sy = 16;
  384.                 p->hit_cx = 24;
  385.             }
  386.             break;
  387.  
  388.             /* 左右からなぎ倒し弾 */
  389.         case 3:
  390.             p->s_work2++;
  391. #define INTERVAL1    6
  392. #define SPEED_SHOT1    15    /* 左右からなぎ倒し弾の速度 */
  393. #define INTERVAL1_1    9
  394. #define SPEED_SHOT1_1    23    /* 自機を狙ってくる単発弾の速度 */
  395.             if (p->s_work2 > INTERVAL1) {
  396.                 p->s_work2 = 0;
  397.                 p->s_work3++;
  398.                 if (p->s_work3 == 1) {
  399.                     p->s_angle = 64 + 48;
  400.                     p->s_angle2 = 64 - 48;
  401.                 }
  402.                 EshotInit (ESHOT_NRG04, p->x - 16, p->y, SPEED_SHOT1, p->s_angle, 0);
  403.                 EshotInit (ESHOT_NRG04, p->x + 16, p->y, SPEED_SHOT1, p->s_angle2, 0);
  404.                 p->s_angle -= 12;
  405.                 p->s_angle2 += 12;
  406.                 SoundSetSE (SE_ESHOT);    /* 敵ショット音 */
  407.  
  408.                 if (p->s_work3 >= 80) {
  409.                     if (!eshot_erase)
  410.                         eshot_erase = ESHOT_ERASE;    /* 弾消し */
  411.                     p->s_work++;    /* 次の攻撃へ */
  412.                     p->s_work2 = p->s_work3 = p->angle = 0;
  413.                 }
  414.             }
  415.             p->s_work4++;
  416.             if (p->s_work4 > INTERVAL1_1) {
  417.                 p->s_work4 = 0;
  418.                 EshotInit (ESHOT_NRG02, p->x, p->y - 12, SPEED_SHOT1_1, psearch (p->x, p->y), 5);
  419.                 SoundSetSE (SE_ESHOT_M);    /* 敵ショット音 */
  420.             }
  421.             if (p->hp < HP_2) {
  422.                 p->s_work = S_WORK_LAST;
  423.                 p->s_work2 = p->s_work3 = 0;
  424.             }
  425.             break;
  426.  
  427.             /* 2箇所からばらまき弾 */
  428.         case 4:
  429.             p->s_work2++;
  430. #define SPEED_SHOT3        12
  431. #define SPEED_SHOT3_1    18
  432. #define SPEED_SHOT3_2    10
  433.             switch (p->s_work2) {
  434.             case 1:
  435.                 EshotInit (ESHOT_NRG02, p->x - 16, p->y, SPEED_SHOT3, rndtable[p->angle++] & 0xfe, 4);
  436.                 EshotInit (ESHOT_NRG02, p->x + 16, p->y, SPEED_SHOT3, rndtable[p->angle++] & 0xfe, 4);
  437.                 EshotInit (ESHOT_NRG24N, p->x, p->y - 12, SPEED_SHOT3_1, rndtable[p->angle++] & 0xfe, 4);
  438.                 SoundSetSE (SE_ESHOT);    /* 敵ショット音 */
  439.                 break;
  440.             case 2:
  441.                 EshotInit (ESHOT_NRG03, p->x - 16, p->y, SPEED_SHOT3_1, rndtable[p->angle++] & 0xfe, 4);
  442.                 EshotInit (ESHOT_NRG03, p->x + 16, p->y, SPEED_SHOT3_1, rndtable[p->angle++] & 0xfe, 4);
  443.                 EshotInit (ESHOT_NRG24N, p->x, p->y - 12, SPEED_SHOT3_1, rndtable[p->angle++] & 0xfe, 4);
  444.                 EshotInit (ESHOT_NRG34N, p->x, p->y - 12, SPEED_SHOT3_2, rndtable[p->angle++] & 0xfe, 4);
  445.                 break;
  446.             case 3:
  447.                 p->s_work2 = 0;
  448.                 break;
  449.             }
  450.             p->s_work3++;
  451.             if (p->s_work3 > 350) {
  452.                 p->s_work++;
  453.                 p->s_work2 = p->s_work3 = p->s_work4 = 0;
  454.                 if (!eshot_erase)
  455.                     eshot_erase = ESHOT_ERASE;    /* 弾消し */
  456.             }
  457.             if (p->hp < HP_2) {
  458.                 p->s_work = S_WORK_LAST;
  459.                 p->s_work2 = p->s_work3 = 0;
  460.             }
  461.             break;
  462.  
  463.             /* 炸裂弾連発 */
  464.         case 5:
  465.             p->s_work2++;
  466.             {
  467.                 unsigned char a;
  468.                 short h;
  469. #define SPEED_SHOT5_1    18
  470. #define SPEED_SHOT5_2    16
  471. #define INTERVAL5    13
  472.                 switch (p->s_work2) {
  473.                 case INTERVAL5 * 1:
  474.                     a = 0;
  475.                     for (h = 0; h < 16; h++)
  476.                         EshotInit (ESHOT_NRG03, p->x, p->y - 10 - 8, SPEED_SHOT5_1, a += 16, 3);
  477.                     SoundSetSE (SE_EBOMB_M);
  478.                     break;
  479.                 case INTERVAL5 * 1 + 1:
  480.                     a = 8;
  481.                     for (h = 0; h < 16; h++)
  482.                         EshotInit (ESHOT_NRG03, p->x, p->y - 10 - 8, SPEED_SHOT5_2, a += 16, 4);
  483.                     break;
  484.                 case INTERVAL5 * 2:
  485.                     a = 0;
  486.                     for (h = 0; h < 16; h++)
  487.                         EshotInit (ESHOT_NRG02, p->x - 12, p->y - 8, SPEED_SHOT5_2, a += 16, 3);
  488.                     SoundSetSE (SE_EBOMB_M);
  489.                     break;
  490.                 case INTERVAL5 * 2 + 1:
  491.                     a = 8;
  492.                     for (h = 0; h < 16; h++)
  493.                         EshotInit (ESHOT_NRG04, p->x - 12, p->y - 8, SPEED_SHOT5_2, a += 16, 4);
  494.                     break;
  495.                 case INTERVAL5 * 3:
  496.                     a = 0;
  497.                     for (h = 0; h < 16; h++)
  498.                         EshotInit (ESHOT_NRG02, p->x + 12, p->y - 8, SPEED_SHOT5_2, a += 16, 3);
  499.                     SoundSetSE (SE_EBOMB_M);
  500.                     break;
  501.                 case INTERVAL5 * 3 + 1:
  502.                     a = 8;
  503.                     for (h = 0; h < 16; h++)
  504.                         EshotInit (ESHOT_NRG04, p->x + 12, p->y - 8, SPEED_SHOT5_1, a += 16, 4);
  505.                     break;
  506.                 case INTERVAL5 * 4:
  507.                     p->s_work2 = 0;
  508.                     break;
  509.                 default:
  510.                     break;
  511.                 }
  512.             }
  513.             p->s_work3++;
  514.             if (p->s_work3 > 350) {
  515.                 p->s_work -= 2;
  516.                 p->s_work2 = p->s_work3 = p->s_work4 = 0;
  517.                 if (!eshot_erase)
  518.                     eshot_erase = ESHOT_ERASE;    /* 弾消し */
  519.             }
  520.             if ((p->hp < HP_2) || (p->timer > TIMER_1)) {
  521.                 p->s_work = S_WORK_LAST;
  522.                 p->s_work2 = p->s_work3 = 0;
  523.             }
  524.             break;
  525.  
  526.             /* ラスボス最終攻撃 */
  527.         case S_WORK_LAST:
  528.             EffectInit (EFFECT_EXPL, 0, p->x, p->y);
  529.             SoundSetSE (SE_EXPL_M);    /* 中ボス爆発音 */
  530.             if (!eshot_erase)
  531.                 eshot_erase = ESHOT_ERASE;    /* 弾消し */
  532.             p->s_work++;
  533.             p->s_work2 = p->s_work3 = 0;
  534.             break;
  535.  
  536.         case S_WORK_LAST + 1:
  537.             {
  538.                 short h;
  539.                 char a;
  540.                 p->s_work2++;
  541.                 switch (p->s_work2) {
  542. #define INTERVAL6    5
  543. #define SPEED_SHOT6    25
  544. #define SPEED_SHOT6_1    15
  545.                 case INTERVAL6 * 1:
  546.                 case INTERVAL6 * 2:
  547.                 case INTERVAL6 * 3:
  548.                 case INTERVAL6 * 4:
  549.                 case INTERVAL6 * 5:
  550.                 case INTERVAL6 * 6:
  551.                     a = 0;
  552.                     for (h = 0; h < 16; h++)
  553.                         EshotInit (ESHOT_NRG02, p->x, p->y - 8, SPEED_SHOT6, a += 16, 4);
  554.                     SoundSetSE (SE_ESHOT_M);    /* 敵ショット音 */
  555.                     break;
  556.                 case INTERVAL6 * 7:
  557.                 case INTERVAL6 * 8:
  558.                 case INTERVAL6 * 9:
  559.                 case INTERVAL6 * 10:
  560.                 case INTERVAL6 * 11:
  561.                 case INTERVAL6 * 12:
  562.                     a = 8;
  563.                     for (h = 0; h < 16; h++)
  564.                         EshotInit (ESHOT_NRG03, p->x, p->y - 8, SPEED_SHOT6, a += 16, 4);
  565.                     SoundSetSE (SE_ESHOT_M);    /* 敵ショット音 */
  566.                     break;
  567.                 case INTERVAL6 * 13:
  568.                     a = psearch (p->x, p->y);    /* 自機の方向をサーチ */
  569.                     for (h = 0; h < 16; h++)
  570.                         EshotInit (ESHOT_NRG35, p->x, p->y - 8, SPEED_SHOT6_1, a += 16, 4);
  571.                     p->s_work2 = 0;
  572.                     break;
  573.                 }
  574.             }
  575.  
  576.             if ((p->hp < HP_3) || (p->timer > TIMER_2)) {
  577.                 p->damage += 5;
  578.                 p->s_work3++;
  579.                 switch (p->s_work3) {
  580.                 case 1:
  581.                     EffectInit (EFFECT_LASTLASER, 0, p->x, p->y);
  582.                     SoundSetSE (SE_BOMB_C);    /* ボンバー音(レーザー) */
  583.                     break;
  584.                 case 15:
  585.                     EffectInit (EFFECT_LASTLASER, 0, p->x + 20, p->y);
  586.                     SoundSetSE (SE_BOMB_C);    /* ボンバー音(レーザー) */
  587.                     if (!eshot_erase)
  588.                         eshot_erase = ESHOT_ERASE;    /* 弾消し */
  589.                     break;
  590.                 case 40:
  591.                     EffectInit (EFFECT_LASTLASER, 0, p->x - 35, p->y);
  592.                     SoundSetSE (SE_BOMB_C);    /* ボンバー音(レーザー) */
  593.                     if (!eshot_erase)
  594.                         eshot_erase = ESHOT_ERASE;    /* 弾消し */
  595.                     break;
  596.                 case 50:
  597.                     EffectInit (EFFECT_LASTLASER, 0, p->x + 4, p->y);
  598.                     SoundSetSE (SE_BOMB_C);    /* ボンバー音(レーザー) */
  599.                     if (!eshot_erase)
  600.                         eshot_erase = ESHOT_ERASE;    /* 弾消し */
  601.                     break;
  602.                 case 75:
  603.                     EffectInit (EFFECT_LASTLASER, 0, p->x - 48, p->y);
  604.                     SoundSetSE (SE_BOMB_C);    /* ボンバー音(レーザー) */
  605.                     if (!eshot_erase)
  606.                         eshot_erase = ESHOT_ERASE;    /* 弾消し */
  607.                     if (p->hp > 0)
  608.                         p->hp = 0;    /* とにかく死ぬ */
  609.                     break;
  610.                 }
  611.             }
  612.             break;
  613.  
  614.         default:
  615.             break;
  616.         }        /* end of switch(p->s_work) */
  617.         break;
  618.  
  619.     case SEQ_DEATH:
  620.         switch (p->m_work) {
  621.         case 0:
  622.             if (SubEnemyMoveToAbort (p) < 0) {    /* 止まるまで待つ */
  623.                 p->m_work++;
  624.                 p->m_work2 = p->m_work3 = 0;
  625.                 SubEnemyMoveToInit (p, p->x, 256 + 64, SPEED_3, SPEED_3N);
  626.                 /* 当たり判定を無くす */
  627.                 p->hit_px = p->hit_py = p->hit_sx = p->hit_sy = p->hit_cx = 0;
  628.                 if (!eshot_erase)
  629.                     eshot_erase = ESHOT_ERASE;    /* 弾消し */
  630.             }
  631.             break;
  632.         case 1:    /* 爆発しながら下に落ちる */
  633.             if (SubEnemyMoveTo (p) < 0)
  634.                 p->m_work++;
  635.  
  636.             if (p->m_work2++ > 3) {
  637.                 signed short x, y;
  638.                 p->m_work2 = 0;
  639.                 x = rndtable[(p->timer) & 0xff ^ 0x55] - 128;
  640.                 y = rndtable[(p->timer) & 0xff ^ 0xaa] - 128;
  641.                 /* p->timer は乱数の種として使用しています */
  642.                 EffectInit (EFFECT_EXPL, 0, x / 2 + p->x, y / 4 + p->y);
  643.                 SoundSetSE (SE_EXPL_M);    /* 中ボス爆発音 */
  644.             }
  645.             p->m_work3++;
  646. #define    TIMER_LASTPLAYER    55
  647.             switch (p->m_work3) {
  648.             case TIMER_LASTPLAYER + 1:
  649.                 EffectInit (EFFECT_LASTPLAYER, 0, 144, 256 + 16);
  650.                 break;
  651.             case TIMER_LASTPLAYER + 15:
  652.                 EffectInit (EFFECT_LASTPLAYER, 0, 144 + 20, 256 + 32);
  653.                 break;
  654.             case TIMER_LASTPLAYER + 40:
  655.                 EffectInit (EFFECT_LASTPLAYER, 0, 144 - 35, 256 + 48);
  656.                 break;
  657.             case TIMER_LASTPLAYER + 50:
  658.                 EffectInit (EFFECT_LASTPLAYER, 0, 144 + 4, 256 + 64);
  659.                 break;
  660.             case TIMER_LASTPLAYER + 75:
  661.                 EffectInit (EFFECT_LASTPLAYER, 0, 144 - 48, 256 + 56);
  662.                 break;
  663.             default:
  664.                 break;
  665.             }
  666.  
  667.             break;
  668.         case 2:
  669.             return (-1);    /* 消去 */
  670.             break;
  671.         }
  672.         break;
  673.  
  674.     default:
  675.         break;
  676.     }            /* end of switch(p->seq) */
  677.  
  678.  
  679.     /* 自機ショットに当たった時の処理 */
  680.     if (p->damage) {
  681.         if (p->seq >= SEQ_DAMAGE) {
  682.             if (p->damage_core) {
  683.                 SoundSetSE (SE_CORE_DAMAGE);
  684.                 p->info = PALET_RED | PRIORITY_BOSS;
  685.                 p->damage_core = 0;
  686.             } else {
  687.                 SoundSetSE (SE_DAMAGE);
  688.                 p->info = PALET_DAMAGE | PRIORITY_BOSS;
  689.             }
  690.             if ((p->hp -= p->damage) <= 0) {
  691.                 /* 死んだ */
  692.                 p->seq = SEQ_DEATH;
  693.                 p->m_work = 0;
  694.             }
  695.             p->damage = 0;
  696.             p->flash = TIMER_FLASH_DAMAGE;
  697.         } else {
  698.             SoundSetSE (SE_NO_DAMAGE);
  699.             p->damage = 0;
  700.         }
  701.     } else {
  702.         if ((p->flash++ > TIMER_FLASH_RED)
  703.             && ((p->hp < 500) || ((p->seq == 5) && (p->hp < HP_1 + 500) && (p->s_work == 0)))) {
  704.             p->info = PALET_RED | PRIORITY_BOSS;
  705.             if (p->flash > TIMER_FLASH_NORMAL)
  706.                 p->flash = 0;
  707.         } else {
  708.             p->info = PALET_LBOSS04 | PRIORITY_BOSS;
  709.         }
  710.     }
  711.  
  712.     xobj_set_st (p);
  713.  
  714.     /* コアの表示 */
  715.     if (p->core_info) {
  716.         p->core_x = p->x;
  717.         p->core_y = p->y - 8;
  718.         xobj_set_st (&(p->core_x));
  719.     }
  720.     return (0);
  721. }
  722.  
  723.  
  724.  
  725. static void EnemyTiniLBoss04 (ENEMY * p)
  726. {
  727.     /* パーツが存在していたら消すように指示 */
  728.     if (p->parts1)
  729.         p->parts1->child_kill = !0;
  730.     if (p->parts2)
  731.         p->parts2->child_kill = !0;
  732.     if (p->parts3)
  733.         p->parts3->child_kill = !0;
  734.     entry_counter_stop = 0;    /* エントリーカウンター停止解除 */
  735. }
  736.